// @HEADER
//*********************************************************************//
//  SiYuan: A numerical PDE solver                                     //
//  Copyright (2022) YUAN Xi                                           //
//  This Software is released under the BSD 2-Clause license detailed  //
//  in the file "LICENSE" in the top-level SiYuan directory            //
//*********************************************************************//
// @HEADER

#ifndef _NOX_OBSERVER_FACTORY_HPP
#define _NOX_OBSERVER_FACTORY_HPP

#include "PanzerAdaptersSTK_config.hpp"

#include "Panzer_ResponseLibrary.hpp"
#include "Panzer_Traits.hpp"
#include "NOX_PrePostOperator_Vector.H"

#include "Teuchos_ParameterList.hpp"
#include "Teuchos_ParameterListAcceptorDefaultBase.hpp"
#include "Teuchos_StandardParameterEntryValidators.hpp"

// Individual Observers
#include "NOXObserver_WriteToExodus.hpp"

namespace SiYuan {
  
  class NOXObserverFactory :
    public Teuchos::ParameterListAcceptorDefaultBase  {
    
    //! Store STK IO response library...be careful, it will be modified externally
    Teuchos::RCP<panzer::ResponseLibrary<panzer::Traits> > stkIOResponseLibrary_;

    mutable Teuchos::RCP<Teuchos::ParameterList> valid_params_;

  public:

    NOXObserverFactory(const Teuchos::RCP<panzer::ResponseLibrary<panzer::Traits> > & stkIOResponseLibrary)
       : stkIOResponseLibrary_(stkIOResponseLibrary) {}
    
    Teuchos::RCP<NOX::Abstract::PrePostOperator>
    buildNOXObserver(const Teuchos::RCP<panzer_stk::STK_Interface>& mesh,
		     const Teuchos::RCP<const panzer::GlobalIndexer>& dof_manager,
		     const Teuchos::RCP<const panzer::LinearObjFactory<panzer::Traits> >& lof) const
    {
      TEUCHOS_ASSERT(nonnull(this->getParameterList()));

      Teuchos::RCP<NOX::PrePostOperatorVector> observer = Teuchos::rcp(new NOX::PrePostOperatorVector);

      // Exodus writer to output solution
      if (this->getParameterList()->get<bool>("Write to Exodus") == true) {
	      Teuchos::RCP<NOX::Abstract::PrePostOperator> solution_writer = 
	        Teuchos::rcp(new NOXObserver_WriteToExodus(mesh,dof_manager,lof,stkIOResponseLibrary_));
	      observer->pushBack(solution_writer);
      }

      return observer;
    }

    /** \name Overridden from Teuchos::ParameterListAcceptor */
    //@{
    
    void setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList)
    {
    //  paramList->validateParametersAndSetDefaults(*(this->getValidParameters()));
      setMyParamList(paramList);
    }
    
    Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const
    {
      if (valid_params_.is_null()) {
	
	valid_params_ = Teuchos::rcp(new Teuchos::ParameterList);
  valid_params_->set<std::string>("File Name","");

	Teuchos::setStringToIntegralParameter<int>(
          "Write to Exodus",
          "ON",
          "Enables or disables writing of solution to Exodus file at end of NOX solve",
          Teuchos::tuple<std::string>("ON","OFF"),
          valid_params_.get()
          );
	Teuchos::setStringToIntegralParameter<int>(
          "Neumann BC Analytic System Test",
          "OFF",
          "Checks solution values for Neumann BC Analytic System Test",
          Teuchos::tuple<std::string>("ON","OFF"),
          valid_params_.get()
          );

      }
      return valid_params_;
    }
 
    //@}

  };

}

#endif
